﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using FFmpegVideoClip.Configuration;
using FFmpegVideoClip.Lib.AudioSpectrogram;
using FFmpegVideoClip.Lib.Effects;


namespace FFmpegVideoClip.Lib.Controls
{
    public class TimeLineSlider : Slider
    {
        public delegate void WavSpectrogramUpdateRoutedEventHandler(TimeLineSlider sender, RoutedEventArgs e);
        public delegate void ZoomLevelChangeRoutedEventHandler(TimeLineSlider sender, ZoomLevelChangeEventArgs e);
        public delegate void TimeLineChangeRoutedEventHandler(TimeLineSlider sender, TimeLineChangeEventArgs e);
        public delegate void MouseSelectValueChangeRoutedEventHandler(TimeLineSlider sender, MouseSelectValueChangeEventArgs e);
        public class MouseSelectValueChangeEventArgs : RoutedEventArgs
        {
            public TimeSpan SelectNewValue;
            public TimeSpan OldValue;
            public MouseSelectValueChangeEventArgs(RoutedEvent routedEvent) : base(routedEvent) { }
            public MouseSelectValueChangeEventArgs(RoutedEvent routedEvent, double NewMillisecondsValue, double oldMillisecondsValue) : this(routedEvent) { SelectNewValue = TimeSpan.FromMilliseconds(NewMillisecondsValue); OldValue = TimeSpan.FromMilliseconds(oldMillisecondsValue); }
            public MouseSelectValueChangeEventArgs(RoutedEvent routedEvent, TimeSpan NewValue, TimeSpan oldValue) : this(routedEvent) { SelectNewValue = NewValue; OldValue = oldValue; }
        }
        public class ZoomLevelChangeEventArgs : RoutedEventArgs
        {
            public int NewZoomLevel;
            public int OldZoomLevel;
            public ZoomLevelChangeEventArgs(RoutedEvent routedEvent) : base(routedEvent) { }
            public ZoomLevelChangeEventArgs(RoutedEvent routedEvent, int NewValue, int OldValue) : this(routedEvent) { NewZoomLevel = NewValue; OldZoomLevel = OldValue; }
        }
        public class TimeLineChangeEventArgs : RoutedEventArgs
        {
            public int CurrentZoomLevel;
            public TimeSpan CurrentZoomMaxTime, CurrentZoomMinTime;
            public TimeLineChangeEventArgs(RoutedEvent routedEvent) : base(routedEvent) { }
            public TimeLineChangeEventArgs(RoutedEvent routedEvent, int zoomLevel, TimeSpan ZoomMinTime, TimeSpan ZoomMaxTime) : this(routedEvent) { CurrentZoomLevel = zoomLevel; CurrentZoomMinTime = ZoomMinTime; CurrentZoomMinTime = ZoomMaxTime; }
        }

        public static readonly Color WavSpectrogramColorDefault = Colors.LimeGreen;
        public static readonly TimeSpan OneSecond = TimeSpan.FromSeconds(1);
        public static readonly TimeSpan Millisecond_10 = TimeSpan.FromMilliseconds(10);


        public TimeSpan[] ZoomLevelValues = [];
        public int MaxZoomLevel => ZoomLevelValues.Length;
        private TimeLineThumbs? m_TimeLineThumbs;
        private Border? m_WavSpectrogram;
        private BrightnessEffect? effect;
        private Track? m_Track;
        private Thumb? m_Thumb;
        private TimeLineTickMarks? m_TickMarks;
        private float FileMaxVolume = 0;
        private bool IsOnShow = false;
        private ContextMenu m_EditMenu = new ContextMenu();
        MenuItem EnableTickMarksEdit_menuItem = new MenuItem();

        
        private void InitContextMenu() { m_EditMenu.Items.Add(EnableTickMarksEdit_menuItem); EnableTickMarksEdit_menuItem.Click += EnableTickMarksEdit_Click; }
        public TimeLineSlider() : base() { InitContextMenu(); IsSnapToTickEnabled = false; IsMoveToPointEnabled = true; 
            IsEnabledChanged += TimeLineSlider_IsEnabledChanged; this.Loaded += TimeLineSlider_Loaded; }
        private void TimeLineSlider_IsEnabledChanged(object sender, DependencyPropertyChangedEventArgs e) { if ((bool)e.NewValue) OnZoomLevelChange(ZoomLevel); }
        private void TimeLineSlider_Loaded(object sender, RoutedEventArgs e) 
        {
            Loaded -= TimeLineSlider_Loaded;
            m_Track = Tools.GetChilds<Track>(this).FirstOrDefault(); 
            m_Thumb = Tools.GetChilds<Thumb>(this).FirstOrDefault();
            m_TickMarks = Tools.GetChilds<TimeLineTickMarks>(this).FirstOrDefault();
            m_TimeLineThumbs = Tools.GetChilds<TimeLineThumbs>(this).First();
            m_WavSpectrogram = Tools.GetChilds<Border>(this).Where(p => p.Tag?.ToString()?.Equals("WavSpectrogramImage", StringComparison.OrdinalIgnoreCase) ?? false).First();
            effect = new BrightnessEffect();
            effect.IsMultiply = true;
            effect.Brightness = 1;
            effect.AddColor = WavSpectrogramColor;
            m_WavSpectrogram.Effect = effect;
        }





        public Color WavSpectrogramColor { get => (Color)GetValue(WavSpectrogramColorProperty); set => SetValue(WavSpectrogramColorProperty, value); }
        public static readonly DependencyProperty WavSpectrogramColorProperty = DependencyProperty.Register(nameof(WavSpectrogramColor), typeof(Color), typeof(TimeLineSlider), new PropertyMetadata(WavSpectrogramColorDefault, (s, e) => 
        {
            TimeLineSlider slider = (TimeLineSlider)s;
            if (slider.effect != null)
                slider.effect.AddColor = (Color)e.NewValue;
        }));

        public double WavSpectrogramTransparent { get => (double)GetValue(WavSpectrogramTransparentProperty); set => SetValue(WavSpectrogramTransparentProperty, value); }
        public static readonly DependencyProperty WavSpectrogramTransparentProperty = DependencyProperty.Register(nameof(WavSpectrogramTransparent), typeof(double), typeof(TimeLineSlider), new PropertyMetadata(1d, (s, e) => 
        {
            TimeLineSlider slider = (TimeLineSlider)s;
            if (slider.m_WavSpectrogram != null)
                slider.m_WavSpectrogram.Opacity = (double)e.NewValue;
        }));

        public double ThumbTransparent { get => (double)GetValue(ThumbTransparentProperty); set => SetValue(ThumbTransparentProperty, value); }
        public static readonly DependencyProperty ThumbTransparentProperty = DependencyProperty.Register(nameof(ThumbTransparent), typeof(double), typeof(TimeLineSlider), new PropertyMetadata(1d, (s, e) => 
        {
            TimeLineSlider slider = (TimeLineSlider)s;
            if (slider.m_TimeLineThumbs != null)
                slider.m_TimeLineThumbs.Opacity = (double)e.NewValue;
        }));

        public bool EnableThumbImage { get => (bool)GetValue(EnableThumbImageProperty); set => SetValue(EnableThumbImageProperty, value); }
        public static readonly DependencyProperty EnableThumbImageProperty = DependencyProperty.Register(nameof(EnableThumbImage), typeof(bool), typeof(TimeLineSlider), new PropertyMetadata(false, (s, e) => 
        {
            TimeLineSlider slider = (TimeLineSlider)s;
            if (slider.m_TimeLineThumbs == null) return;
            slider.m_TimeLineThumbs.EnableThumbImage = (bool)e.NewValue;
        }));


        public Brush? WavSpectrogramImage { get => (Brush)GetValue(WavSpectrogramImageProperty); set => SetValue(WavSpectrogramImageProperty, value); }
        public static readonly DependencyProperty WavSpectrogramImageProperty = DependencyProperty.Register(nameof(WavSpectrogramImage), typeof(Brush), typeof(TimeLineSlider), 
            new PropertyMetadata(AudioWavSpectrogram.BlankSpectrogramImageBrush));

        [Bindable(true)] public bool EnableCursorTracking { get => (bool)GetValue(EnableCursorTrackingProperty); set => SetValue(EnableCursorTrackingProperty, value); }
        public static readonly DependencyProperty EnableCursorTrackingProperty = DependencyProperty.Register(nameof(EnableCursorTracking), typeof(bool), typeof(TimeLineSlider), new PropertyMetadata(false));

        public event WavSpectrogramUpdateRoutedEventHandler WavSpectrogramUpdateEvent { add => AddHandler(WavSpectrogramUpdateRoutedEvent, value); remove => RemoveHandler(WavSpectrogramUpdateRoutedEvent, value); }
        public static readonly RoutedEvent WavSpectrogramUpdateRoutedEvent = EventManager.RegisterRoutedEvent(nameof(WavSpectrogramUpdateEvent), RoutingStrategy.Direct, typeof(WavSpectrogramUpdateRoutedEventHandler), typeof(TimeLineSlider));
        public void SendWavSpectrogramUpdateEvent() => RaiseEvent(new RoutedEventArgs(WavSpectrogramUpdateRoutedEvent));

        public event ZoomLevelChangeRoutedEventHandler ZoomLevelChangeEvent { add => AddHandler(ZoomLevelChangeRoutedEvent, value); remove => RemoveHandler(ZoomLevelChangeRoutedEvent, value); }
        public static readonly RoutedEvent ZoomLevelChangeRoutedEvent = EventManager.RegisterRoutedEvent(nameof(ZoomLevelChangeEvent), RoutingStrategy.Direct, typeof(ZoomLevelChangeRoutedEventHandler), typeof(TimeLineSlider));

        public event TimeLineChangeRoutedEventHandler TimeLineChangeEvent { add => AddHandler(TimeLineChangeRoutedEvent, value); remove => RemoveHandler(TimeLineChangeRoutedEvent, value); }
        public static readonly RoutedEvent TimeLineChangeRoutedEvent = EventManager.RegisterRoutedEvent(nameof(TimeLineChangeEvent), RoutingStrategy.Direct, typeof(TimeLineChangeRoutedEventHandler), typeof(TimeLineSlider));
        private void RaiseTimeLineChange() => RaiseEvent(new TimeLineChangeEventArgs(TimeLineChangeRoutedEvent, ZoomLevel, CurrentZoomMinTime, CurrentZoomMaxTime));

        public event MouseSelectValueChangeRoutedEventHandler MouseSelectValueChangeEvent { add => AddHandler(MouseSelectValueChangeRoutedEvent, value); remove => RemoveHandler(MouseSelectValueChangeRoutedEvent, value); }
        public static readonly RoutedEvent MouseSelectValueChangeRoutedEvent = EventManager.RegisterRoutedEvent(nameof(MouseSelectValueChangeEvent), RoutingStrategy.Direct, typeof(MouseSelectValueChangeRoutedEventHandler), typeof(TimeLineSlider));
        private void RaiseMouseSelectValueChange(double NewValue, double OldValue) => RaiseEvent(new MouseSelectValueChangeEventArgs(MouseSelectValueChangeRoutedEvent, NewValue, OldValue));
        [Bindable(true)] public TimeSpan MaxTime { get => (TimeSpan)GetValue(MaxTimeProperty); set => SetValue(MaxTimeProperty, value); }
        public static readonly DependencyProperty MaxTimeProperty = DependencyProperty.Register(nameof(MaxTime), typeof(TimeSpan), typeof(TimeLineSlider), new PropertyMetadata(TimeSpan.MinValue, (s, e) => 
        {
            TimeLineSlider slider = (TimeLineSlider)s;
            TimeSpan value = (TimeSpan)e.NewValue;
            slider.ZoomLevelValues = Config.ZoomValues.Where(p => p < value).ToArray();
            slider.UpdateWavSpectrogramToZeroLevel();
        }));

        [Bindable(true)] public int ZoomLevel { get => (int)GetValue(CurrentZoomLevelProperty); set
            {
                int v = value < 0 ? 0 : value > MaxZoomLevel ? MaxZoomLevel : value;
                if ((int)GetValue(CurrentZoomLevelProperty) != v)
                    SetValue(CurrentZoomLevelProperty, v);
            } }
        public static readonly DependencyProperty CurrentZoomLevelProperty = DependencyProperty.Register(nameof(ZoomLevel), typeof(int), typeof(TimeLineSlider), new PropertyMetadata(0, (s, e) =>
        {
            TimeLineSlider slider = (TimeLineSlider)s;
            ZoomLevelChangeEventArgs args = new(ZoomLevelChangeRoutedEvent, (int)e.NewValue, (int)e.OldValue);
            slider.OnZoomLevelChange(args.NewZoomLevel);
            slider.RaiseEvent(args);
        }));

        [Bindable(true)] public TimeSpan CurrentZoomMaxTimeRangeEdge { get => (TimeSpan)GetValue(CurrentZoomMaxTimeRangeEdgeProperty); private set => SetValue(CurrentZoomMaxTimeRangeEdgeProperty, value); }
        public static readonly DependencyProperty CurrentZoomMaxTimeRangeEdgeProperty = DependencyProperty.Register(nameof(CurrentZoomMaxTimeRangeEdge), typeof(TimeSpan), typeof(TimeLineSlider), new PropertyMetadata(TimeSpan.Zero));
        [Bindable(true)] public TimeSpan CurrentZoomMaxTime { get => (TimeSpan)GetValue(CurrentZoomMaxTimeProperty); private set => SetValue(CurrentZoomMaxTimeProperty, value); }
        public static readonly DependencyProperty CurrentZoomMaxTimeProperty = DependencyProperty.Register(nameof(CurrentZoomMaxTime), typeof(TimeSpan), typeof(TimeLineSlider), new PropertyMetadata(TimeSpan.MinValue, (s, e) =>
        {
            TimeLineSlider slider = (TimeLineSlider)s;
            TimeSpan ts = (TimeSpan)e.NewValue;
            if (slider.Maximum != ts.TotalMilliseconds)
                slider.Maximum = ts.TotalMilliseconds;
        }));

        [Bindable(true)] public TimeSpan CurrentZoomMinTimeRangeEdge { get => (TimeSpan)GetValue(CurrentZoomMinTimeRangeEdgeProperty); private set => SetValue(CurrentZoomMinTimeRangeEdgeProperty, value); }
        public static readonly DependencyProperty CurrentZoomMinTimeRangeEdgeProperty = DependencyProperty.Register(nameof(CurrentZoomMinTimeRangeEdge), typeof(TimeSpan), typeof(TimeLineSlider), new PropertyMetadata(TimeSpan.Zero));
        [Bindable(true)] public TimeSpan CurrentZoomMinTime { get => (TimeSpan)GetValue(CurrentZoomMinTimeProperty); private set => SetValue(CurrentZoomMinTimeProperty, value); }
        public static readonly DependencyProperty CurrentZoomMinTimeProperty = DependencyProperty.Register(nameof(CurrentZoomMinTime), typeof(TimeSpan), typeof(TimeLineSlider), new PropertyMetadata(TimeSpan.MinValue, (s, e) =>
        {
            TimeLineSlider slider = (TimeLineSlider)s;
            TimeSpan ts = (TimeSpan)e.NewValue;
            if (slider.Minimum != ts.TotalMilliseconds)
                slider.Minimum = ts.TotalMilliseconds;
        }));

        [Bindable(true)] public DoubleCollection TimeRangeEdges { get => (DoubleCollection)GetValue(TimeRangeEdgesProperty); private set => SetValue(TimeRangeEdgesProperty, value); }
        public static readonly DependencyProperty TimeRangeEdgesProperty = DependencyProperty.Register(nameof(TimeRangeEdges), typeof(DoubleCollection), typeof(TimeLineSlider), new PropertyMetadata(new DoubleCollection(2)));
        private void UpdateTimeRangeEdge() => TimeRangeEdges = new DoubleCollection([CurrentZoomMinTimeRangeEdge.TotalMilliseconds, CurrentZoomMaxTimeRangeEdge.TotalMilliseconds]);

        private ImageBrush TopWavSpectrogram { get; set; } = AudioWavSpectrogram.BlankSpectrogramImageBrush;
        private static void CreateWavSpectrogramCancelSource(ref AudioWavSpectrogramCancelSource? CancelSource)
        {
            if (CancelSource != null && !CancelSource.IsClear)
            {
                if (!CancelSource.IsCancellationRequested)
                    CancelSource.Cancel();
                CancelSource.Clear();
            }
            CancelSource = AudioWavSpectrogramCancelSource.Create();
        }
        private AudioWavSpectrogramCancelSource? TopWavSpectrogramCancelSource;
        [Bindable(true)] public string FilePath { get => (string)GetValue(FilePathProperty); set { if (!((string)GetValue(FilePathProperty)).Equals(value, StringComparison.OrdinalIgnoreCase)) SetValue(FilePathProperty, value); } }
        public static readonly DependencyProperty FilePathProperty = DependencyProperty.Register(nameof(FilePath), typeof(string), typeof(TimeLineSlider), new PropertyMetadata(string.Empty, async (s, e) =>
        {
            TimeLineSlider tsl = (TimeLineSlider)s;
            string? path = e.NewValue?.ToString();
            if (!string.IsNullOrEmpty(path) && File.Exists(path))
            {
                tsl.SendWavSpectrogramUpdateEvent();
                CreateWavSpectrogramCancelSource(ref tsl.TopWavSpectrogramCancelSource);
                await Task.WhenAll(
                 Task.Run(() => tsl.FileMaxVolume = AudioWavSpectrogram.GetFileMaxVolume(path, tsl.TopWavSpectrogramCancelSource!, TimeSpan.Zero, TimeSpan.MaxValue))
               , Task.Run(() => tsl.TopWavSpectrogram = AudioWavSpectrogram.CreateWavSpectrogramPng(0, path, tsl.TopWavSpectrogramCancelSource!, default, default)?.Result ?? AudioWavSpectrogram.BlankSpectrogramImageBrush));
                tsl.TopWavSpectrogramCancelSource = null;
            }
            else { tsl.TopWavSpectrogram = AudioWavSpectrogram.BlankSpectrogramImageBrush; tsl.FileMaxVolume = 0; tsl.EnableThumbImage = false; }
            tsl.UpdateWavSpectrogramToZeroLevel();
        }));
        public bool IsFileOpen => !string.IsNullOrWhiteSpace(FilePath);

        private void UpdateWavSpectrogramToZeroLevel() { if (Mouse.LeftButton == MouseButtonState.Pressed) return; if (ZoomLevel == 0) { SetZoomLevel_0(); CallSetWavSpectrogramAsync(0); } else ZoomLevel = 0; }
        private AudioWavSpectrogramCancelSource? WavSpectrogramCancelSource;
        private void CallSetWavSpectrogramAsync(int zoomLevel)
        {
            if (!IsEnabled)
                return;
            SetWavSpectrogramAsync(zoomLevel);
        }

        private void SetWavSpectrogramAsync(int zoomLevel)
        {
            if (zoomLevel == 0)
                WavSpectrogramImage = TopWavSpectrogram;
            else
            {
                TimeSpan mix = CurrentZoomMinTime, Max = CurrentZoomMaxTime;
                _ = Tools.DelayedExecution(() => SetZoomLevelWavSpectrogramAsync(zoomLevel, mix, Max), condition: async () => zoomLevel == await Dispatcher.InvokeAsync(() => ZoomLevel), UseMainThread: true);
            }

        }
        private async Task SetZoomLevelWavSpectrogramAsync(int zoomLevel, TimeSpan mixTime, TimeSpan maxTime)
        {
            CreateWavSpectrogramCancelSource(ref WavSpectrogramCancelSource);
            AudioWavSpectrogramResult? result = await AudioWavSpectrogram.CreateWavSpectrogramPngAsync(zoomLevel, FilePath, WavSpectrogramCancelSource!, mixTime, maxTime, FileMaxVolume);
            if (result != null && result.Result != AudioWavSpectrogram.BlankSpectrogramImageBrush && result.ZoomLevel == ZoomLevel)
                WavSpectrogramImage = result.Result;
        }
        protected virtual void OnZoomLevelChange(int zoomLevel, double? UseValue = null)
        {
            m_Thumb!.CancelDrag();
            if (ZoomLevel == 0)
                SetZoomLevel_0();
            else
                SetZoomLevel(ZoomLevelValues[zoomLevel - 1]);
            SendWavSpectrogramUpdateEvent();
            WavSpectrogramImage = null;
            CallSetWavSpectrogramAsync(zoomLevel);
            RaiseTimeLineChange();
        }
        protected void SetZoomLevel_0()
        {
            CurrentZoomMinTime = TimeSpan.Zero;
            CurrentZoomMaxTime = MaxTime;

            CurrentZoomMinTimeRangeEdge = CurrentZoomMinTime - OneSecond;
            CurrentZoomMaxTimeRangeEdge = CurrentZoomMaxTime + OneSecond;
            UpdateTimeRangeEdge();
        }
        protected void SetZoomLevel(TimeSpan Halflength, double? UseValue = null)
        {
            TimeSpan current = TimeSpan.FromMilliseconds(UseValue.HasValue ? UseValue.Value : Value);
            if (current < CurrentZoomMinTimeRangeEdge)
                current -= Halflength / 2;
            else if (current > CurrentZoomMaxTimeRangeEdge)
                current += Halflength / 2;
            if (current < TimeSpan.Zero)
                current = TimeSpan.Zero;
            else if (current > MaxTime)
                current = MaxTime;
            SetZoomLevel(current - Halflength, current + Halflength);
        }
        public void SetZoomLevel(TimeSpan Start, TimeSpan End)
        {
            CurrentZoomMinTime = Start < TimeSpan.Zero ? TimeSpan.Zero : Start;
            CurrentZoomMaxTime = End > MaxTime ? MaxTime : End;
            TimeSpan RangeExpansion = (CurrentZoomMaxTime - CurrentZoomMinTime) / Config.TimeLineUpdateRangeEdgeExpansionValue;
            CurrentZoomMinTimeRangeEdge = CurrentZoomMinTime <= TimeSpan.Zero ? CurrentZoomMinTime - OneSecond : CurrentZoomMinTime + RangeExpansion;
            CurrentZoomMaxTimeRangeEdge = CurrentZoomMaxTime >= MaxTime ? MaxTime + OneSecond : CurrentZoomMaxTime - RangeExpansion;
            UpdateTimeRangeEdge();
            MouseTracking();
        }
        private void MouseTracking()
        {
            if (!EnableCursorTracking || Maximum - Minimum <= 0 || !IsMouseOver || Mouse.LeftButton != MouseButtonState.Pressed)
                return;
            double SecondsUIWidth = ActualWidth / (Maximum - Minimum);
            double UIPointX= (Value - Minimum) * SecondsUIWidth;
            double UIPointY = Mouse.GetPosition(this).Y;
            Point Screen = PointToScreen(new(UIPointX, UIPointY));
            Tools.SetCursorPos(Screen.X, Screen.Y);
        }
        protected override void OnMouseWheel(MouseWheelEventArgs e)
        {
            if (e.Delta > 0)
                ZoomLevel++;
            else
                ZoomLevel--;
            base.OnMouseWheel(e);
        }
        protected override void OnValueChanged(double oldValue, double newValue)
        {
            if (!IsOnShow)
            {
                TimeSpan ts = TimeSpan.FromMilliseconds(newValue);
                if (ts > CurrentZoomMaxTimeRangeEdge || ts < CurrentZoomMinTimeRangeEdge)
                {
                    OnZoomLevelChange(ZoomLevel);
                }
            }
            if (Mouse.LeftButton == MouseButtonState.Pressed)
                RaiseMouseSelectValueChange(newValue,oldValue);
            base.OnValueChanged(oldValue, newValue);
        }


        protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
        {
            if (IsMoveToPointEnabled && m_Track != null && m_Thumb != null && !m_Thumb.IsMouseOver)
            {
                double num = m_Track.ValueFromPoint(e.MouseDevice.GetPosition(m_Track));
                if (!double.IsInfinity(num) && !double.IsNaN(num))
                {
                    Value = num < Minimum ? Minimum : num > Maximum ? Maximum : num;
                    //Value = Math.Max(Minimum, Math.Min(Maximum, num));
                }
                e.Handled = true;
            }
            base.OnMouseLeftButtonDown(e);
        }
        protected override void OnPreviewMouseLeftButtonDown(MouseButtonEventArgs e) { Focus(); return;/*base.OnPreviewMouseLeftButtonDown(e);*/}


        private void EnableTickMarksEdit_Click(object sender, RoutedEventArgs e) => m_TickMarks!.IsEnableTickMarksEdit = !m_TickMarks!.IsEnableTickMarksEdit;
        private void OpenContextMenu() 
        {
            if (m_TickMarks!.IsEnableTickMarksEdit)
                EnableTickMarksEdit_menuItem.Header = "关闭分割点编辑";
            else
                EnableTickMarksEdit_menuItem.Header = "启用分割点编辑";
            m_EditMenu.IsOpen = true;
        }
        protected override void OnMouseRightButtonDown(MouseButtonEventArgs e)
        {
            if (e.RightButton == MouseButtonState.Pressed)
            {
                if(m_TickMarks!.IsEnableTickMarksEdit)
                {
                    m_TickMarks!.RaiseEvent(e);
                    return;
                }
                e.Handled = true;
                Focus();
                CaptureMouse();
            }
            base.OnMouseRightButtonDown(e);
        }
        protected override void OnMouseRightButtonUp(MouseButtonEventArgs e)
        {
            if (IsMouseCaptured && e.RightButton == MouseButtonState.Released)
            {
                if (m_TickMarks!.IsEnableTickMarksEdit)
                {
                    m_TickMarks!.RaiseEvent(e);
                    return;
                }
                ReleaseMouseCapture();
                OpenContextMenu();
                e.Handled = true;
            }
            base.OnMouseRightButtonUp(e);
        }

        //protected override void OnMouseEnter(MouseEventArgs e)
        //{
        //    Focus();
        //    base.OnMouseEnter(e);
        //}

        //protected override void OnThumbDragDelta(DragDeltaEventArgs e)
        //{
        //    double[] Edge = GetTimeRangeEdgeExtend();
        //    if (Value > Edge[0] && Value < Edge[1])
        //        base.OnThumbDragDelta(e);
        //    else
        //        thumb!.CancelDrag();
        //}
        //private double[] GetTimeRangeEdgeExtend()
        //{
        //    double length = (CurrentZoomMaxTimeRangeEdge - CurrentZoomMinTimeRangeEdge).TotalMilliseconds;
        //    length *= 0.002d;
        //    return new double[] { CurrentZoomMinTimeRangeEdge.TotalMilliseconds + length, CurrentZoomMaxTimeRangeEdge.TotalMilliseconds - length, length };
        //}
        //public bool IsLeaveEdgeExtend
        //{
        //    get 
        //    {
        //        //double[] Edge = GetTimeRangeEdgeExtend();
        //        return Value < CurrentZoomMinTimeRangeEdge.TotalMilliseconds || CurrentZoomMaxTimeRangeEdge.TotalMilliseconds > Edge[1];
        //    }
        //}

        public void OnShow(double value)
        {
            IsOnShow = true;
            TimeSpan ts = TimeSpan.FromMilliseconds(value);
            if (ts > CurrentZoomMaxTimeRangeEdge || ts < CurrentZoomMinTimeRangeEdge)
                OnZoomLevelChange(ZoomLevel,value);
            if (Value != value)
                Value = value;
            IsOnShow = false;
        }
        
        public async Task Clear()
        {
            IEnumerable<TimeLineTickMarks> TickMarks = Tools.GetChilds<TimeLineTickMarks>(this);
            if(TickMarks.Any())
            {
                TickMarks.First().Clear();
            }
            await Task.Run(()=>AudioWavSpectrogramCancelSource.CancelAll());
            FilePath = string.Empty;
        }
    }
}
